load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_test")
load("//bazel:defs.bzl", "rust_ic_bench", "rust_ic_test_suite_with_extra_srcs")
load("//bazel:fuzz_testing.bzl", "DEFAULT_RUSTC_FLAGS_FOR_FUZZING")
load("//rs/tests:common.bzl", "UNIVERSAL_CANISTER_ENV", "UNIVERSAL_CANISTER_RUNTIME_DEPS")

package(default_visibility = ["//visibility:public"])

DATA = [
    "//rs/rust_canisters/stable_structures:stable_structures_canister",
    "//rs/nns/governance:governance-bench-canister",
]

ENV = {
    "STABLE_STRUCTURES_CANISTER_WASM_PATH": "$(rootpath //rs/rust_canisters/stable_structures:stable_structures_canister)",
    "GOVERNANCE_BENCH_CANISTER_WASM_PATH": "$(rootpath //rs/nns/governance:governance-bench-canister)",
}

rust_library(
    name = "embedders",
    srcs = glob(["src/**/*.rs"]),
    crate_name = "ic_embedders",
    rustc_flags = select({
        "//bazel:fuzzing_code_enabled": DEFAULT_RUSTC_FLAGS_FOR_FUZZING,
        "//conditions:default": [],
    }),
    version = "0.9.0",
    deps = [
        # Keep sorted.
        "//packages/ic-error-types",
        "//packages/ic-heap-bytes",
        "//rs/config",
        "//rs/cycles_account_manager",
        "//rs/interfaces",
        "//rs/limits",
        "//rs/memory_tracker",
        "//rs/monitoring/logger",
        "//rs/monitoring/metrics",
        "//rs/nns/constants",
        "//rs/registry/subnet_type",
        "//rs/replicated_state",
        "//rs/sys",
        "//rs/types/base_types",
        "//rs/types/management_canister_types",
        "//rs/types/types",
        "//rs/types/wasm_types",
        "//rs/utils",
        "//rs/utils/lru_cache",
        "@crate_index//:anyhow",
        "@crate_index//:bincode",
        "@crate_index//:candid",
        "@crate_index//:ic-btc-interface",
        "@crate_index//:itertools",
        "@crate_index//:libc",
        "@crate_index//:libflate",
        "@crate_index//:nix",
        "@crate_index//:num-traits",
        "@crate_index//:prometheus",
        "@crate_index//:rustc-demangle",
        "@crate_index//:scopeguard",
        "@crate_index//:serde",
        "@crate_index//:serde_bytes",
        "@crate_index//:slog",
        "@crate_index//:tempfile",
        "@crate_index//:wasm-encoder",
        "@crate_index//:wasmparser",
        "@crate_index//:wasmprinter",
        "@crate_index//:wasmtime",
        "@crate_index//:wasmtime-environ",
        "@crate_index//:wirm",
    ],
)

rust_binary(
    name = "instrument-wasm",
    srcs = ["bin/instrument_wasm.rs"],
    deps = [
        # Keep sorted.
        ":embedders",
        "//rs/config",
        "@crate_index//:bincode",
        "@crate_index//:clap",
        "@crate_index//:slog",
        "@crate_index//:slog-term",
    ],
)

rust_test(
    name = "embedders_test",
    crate = ":embedders",
    deps = [
        # Keep sorted.
        "//rs/interfaces",
        "//rs/test_utilities",
        "//rs/test_utilities/types",
        "@crate_index//:assert_matches",
        "@crate_index//:candid",
        "@crate_index//:lazy_static",
        "@crate_index//:maplit",
        "@crate_index//:proptest",
        "@crate_index//:wat",
    ],
)

rust_test(
    name = "instrumentation",
    srcs = ["tests/instrumentation.rs"],
    crate_root = "tests/instrumentation.rs",
    data = glob(["tests/instrumentation-test-data/*"]) + glob(["tests/snapshots/*"]),
    env = {
        "CARGO_MANIFEST_DIR": "rs/embedders",
        "INSTA_WORKSPACE_ROOT": ".",
    },
    proc_macro_deps = [
        # "@crate_index//:strum_macros",
    ],
    deps = [
        # Keep sorted.
        ":embedders",
        "//rs/config",
        "//rs/interfaces",
        "//rs/monitoring/logger",
        "//rs/replicated_state",
        "//rs/sys",
        "//rs/test_utilities/embedders",
        "//rs/types/management_canister_types",
        "//rs/types/types",
        "//rs/types/wasm_types",
        "@crate_index//:insta",
        "@crate_index//:itertools",
        "@crate_index//:pretty_assertions",
        "@crate_index//:wasmparser",
        "@crate_index//:wasmprinter",
        "@crate_index//:wat",
        "@crate_index//:wirm",
    ],
)

# Run some tests using wasm spec files.
# To add a test suite, see the `http_archive` pulling in the testsuite
# and add a new target.
#
# To inspect the spec files, use this command:
# $ ls $(bazel info output_base)/external/wasm_spec_testsuite
rust_ic_test_suite_with_extra_srcs(
    name = "embedders_integration",
    srcs = glob(
        ["tests/**/*.rs"],
        exclude = [
            "tests/wasmtime_simple.rs",
            "tests/instrumentation.rs",
            "tests/system_api.rs",
            "tests/sandbox_safe_system_state.rs",
        ],
    ),
    compile_data = glob(["tests/instrumentation-test-data/*"]),
    data = DATA + [
        "//rs/universal_canister/impl:universal_canister.module",
        "//rs/universal_canister/impl:universal_canister.wasm.gz",
        "@wasm_spec_testsuite//:base_wast_files",
        "@wasm_spec_testsuite//:memory64_wast_files",
        "@wasm_spec_testsuite//:multi_memory_wast_files",
    ] + glob([
        "tests/compressed/*",
        "tests/instrumentation-test-data/*",
    ]),
    env = dict(ENV.items() + [
        ("CARGO_MANIFEST_DIR", "rs/embedders"),
        ("WASM_SPEC_BASE", "$(locations @wasm_spec_testsuite//:base_wast_files)"),
        ("WASM_SPEC_MULTI_MEMORY", "$(locations @wasm_spec_testsuite//:multi_memory_wast_files)"),
        ("WASM_SPEC_MEMORY64", "$(locations @wasm_spec_testsuite//:memory64_wast_files)"),
        ("UNIVERSAL_CANISTER_SERIALIZED_MODULE_PATH", "$(rootpath //rs/universal_canister/impl:universal_canister.module)"),
        ("UNIVERSAL_CANISTER_WASM_PATH", "$(rootpath //rs/universal_canister/impl:universal_canister.wasm.gz)"),
    ]),
    extra_srcs = [
        "tests/wasmtime_simple.rs",
        "tests/instrumentation.rs",
    ],
    deps = [
        # Keep sorted.
        ":embedders",
        "//packages/ic-error-types",
        "//rs/config",
        "//rs/cycles_account_manager",
        "//rs/interfaces",
        "//rs/monitoring/logger",
        "//rs/nns/constants",
        "//rs/registry/routing_table",
        "//rs/registry/subnet_type",
        "//rs/replicated_state",
        "//rs/rust_canisters/canister_test",
        "//rs/sys",
        "//rs/test_utilities",
        "//rs/test_utilities/embedders",
        "//rs/test_utilities/execution_environment",
        "//rs/test_utilities/logger",
        "//rs/test_utilities/state",
        "//rs/test_utilities/types",
        "//rs/types/base_types",
        "//rs/types/management_canister_types",
        "//rs/types/types",
        "//rs/types/wasm_types",
        "@crate_index//:anyhow",
        "@crate_index//:assert_matches",
        "@crate_index//:lazy_static",
        "@crate_index//:libc",
        "@crate_index//:maplit",
        "@crate_index//:proptest",
        "@crate_index//:wasm-encoder",
        "@crate_index//:wasmparser",
        "@crate_index//:wasmprinter",
        "@crate_index//:wasmtime",
        "@crate_index//:wasmtime-environ",
        "@crate_index//:wast",
        "@crate_index//:wat",
        "@crate_index//:wirm",
    ],
)

rust_test(
    name = "system_api_integration_test",
    srcs = [
        "tests/common/mod.rs",
        "tests/system_api.rs",
    ],
    crate_root = "tests/system_api.rs",
    deps = [
        # Keep sorted.
        ":embedders",
        "//packages/ic-error-types",
        "//rs/config",
        "//rs/cycles_account_manager",
        "//rs/interfaces",
        "//rs/limits",
        "//rs/monitoring/logger",
        "//rs/nns/constants",
        "//rs/registry/routing_table",
        "//rs/registry/subnet_type",
        "//rs/replicated_state",
        "//rs/test_utilities",
        "//rs/test_utilities/state",
        "//rs/test_utilities/types",
        "//rs/types/base_types",
        "//rs/types/management_canister_types",
        "//rs/types/types",
        "@crate_index//:maplit",
        "@crate_index//:more-asserts",
        "@crate_index//:strum",
    ],
)

rust_test(
    name = "sandbox_safe_system_state_test",
    srcs = [
        "tests/common/mod.rs",
        "tests/sandbox_safe_system_state.rs",
    ],
    crate_root = "tests/sandbox_safe_system_state.rs",
    deps = [
        # Keep sorted.
        ":embedders",
        "//rs/config",
        "//rs/cycles_account_manager",
        "//rs/interfaces",
        "//rs/limits",
        "//rs/monitoring/logger",
        "//rs/nns/constants",
        "//rs/registry/routing_table",
        "//rs/registry/subnet_type",
        "//rs/replicated_state",
        "//rs/test_utilities",
        "//rs/test_utilities/state",
        "//rs/test_utilities/types",
        "//rs/types/base_types",
        "//rs/types/management_canister_types",
        "//rs/types/types",
        "@crate_index//:maplit",
        "@crate_index//:prometheus",
    ],
)

rust_library(
    name = "embedders_bench",
    testonly = True,
    srcs = [
        "benches/embedders_bench/src/lib.rs",
    ],
    version = "0.9.0",
    deps = [
        # Keep sorted.
        "//rs/rust_canisters/canister_test",
        "//rs/test_utilities/execution_environment",
        "//rs/types/types",
        "@crate_index//:candid",
        "@crate_index//:criterion",
        "@crate_index//:wirm",
    ],
)

UNIVERSAL_CANISTER_TEST_DEPS = UNIVERSAL_CANISTER_RUNTIME_DEPS + [
    "//rs/universal_canister/impl:universal_canister.module",
]

UNIVERSAL_CANISTER_TEST_ENV = UNIVERSAL_CANISTER_ENV | {
    "UNIVERSAL_CANISTER_SERIALIZED_MODULE_PATH": "$(rootpath //rs/universal_canister/impl:universal_canister.module)",
}

rust_ic_bench(
    name = "compilation_bench",
    testonly = True,
    srcs = ["benches/compilation.rs"],
    compile_data = glob(["benches/test-data/*"]),
    data = DATA + UNIVERSAL_CANISTER_TEST_DEPS,
    env = ENV | UNIVERSAL_CANISTER_TEST_ENV,
    test_name = "compilation_bench_test",
    test_timeout = "long",
    deps = [
        # Keep sorted.
        ":embedders",
        ":embedders_bench",
        "//rs/config",
        "//rs/monitoring/logger",
        "//rs/rust_canisters/canister_test",
        "//rs/types/wasm_types",
        "@crate_index//:candid",
        "@crate_index//:criterion",
        "@crate_index//:lazy_static",
        "@crate_index//:libflate",
        "@crate_index//:rayon",
        "@crate_index//:wat",
    ],
)

rust_ic_bench(
    name = "stable_memory_bench",
    testonly = True,
    srcs = ["benches/stable_memory.rs"],
    data = DATA + UNIVERSAL_CANISTER_TEST_DEPS,
    env = ENV | UNIVERSAL_CANISTER_TEST_ENV,
    deps = [
        # Keep sorted.
        ":embedders_bench",
        "//rs/replicated_state",
        "//rs/rust_canisters/canister_test",
        "//rs/sys",
        "@crate_index//:candid",
        "@crate_index//:criterion",
        "@crate_index//:lazy_static",
        "@crate_index//:wat",
    ],
)

rust_ic_bench(
    name = "heap_bench",
    testonly = True,
    srcs = ["benches/heap.rs"],
    compile_data = glob(["benches/test-data/*"]),
    data = DATA + UNIVERSAL_CANISTER_TEST_DEPS,
    env = ENV | UNIVERSAL_CANISTER_TEST_ENV,
    proc_macro_deps = [
        # Keep sorted.
        "@crate_index//:strum_macros",
    ],
    deps = [
        # Keep sorted.
        ":embedders_bench",
        "//rs/replicated_state",
        "//rs/sys",
        "@crate_index//:criterion",
        "@crate_index//:strum",
        "@crate_index//:wat",
    ],
)
